package com.wsfPro.controllers.item;

import com.wsfPro.core.encryptionDecrypt.EncryptionDecrypt;
import com.wsfPro.util.math.GetKaiFangNumber;

import java.util.Random;

/** 加密id 显示实体的基类 */
public class SuperDisplay implements EncryptionDecrypt {
  private int a;
  private int b;
  private Long cha;
  /** 需要加密的属性sqlId */
  private Long id;
  /** 加密后的id值; */
  private Long encryptionId;

  protected SuperDisplay() {};

  public SuperDisplay(long id) throws Exception {
    int ab[] = this.randomAB();
    a = ab[0];
    b = ab[1];
    this.encryption(a, b, id);
  }

  // 数据库的ID均为正整数就不用考虑小数点问题了
  // 简单加密 解密 随机数random为一元一次函数系数 开根号 一元一次函数
  // 开根号 根据a奇偶确定开根后正负

  public Long encryption(int a, int b, Long id) throws Exception {
    if (a == 0) throw new Exception("a error ,a=" + a);
    if (id == null) throw new Exception("id error,id=" + id);
    if (id.toString().contains(".")) throw new Exception("id error,id=" + id);
    if (id < 0) throw new Exception(" id error,id=" + id);
    // 拿到能开方为整数的数
    long needEncryptionNumber = GetKaiFangNumber.getKaiFangNumber().get(id);
    // 被开方数与id间的差值
    this.cha = needEncryptionNumber - id;
    // 去小数点转为long 获得正开方数
    Long sqrt = new Long(String.valueOf(Math.sqrt(needEncryptionNumber)).split("\\.")[0]);
    // 线性方程系数a为负数则取负开方数
    if (a % 2 != 0) sqrt = sqrt - 2 * sqrt;
    this.encryptionId = linearEquationOneUnknown(a, b, sqrt);
    this.id = id;
    return encryptionId;
  }

  // 解密
  //	public Long Decrypt(Long needDecryptNumber, Long cha) {
  //		Long _sqrt = linearEquationOneUnknownDecrypt(this.a, this.b,
  //				needDecryptNumber);
  //		return _sqrt * _sqrt - cha;
  //	}
  /**
   * 获取sqlId
   *
   * @return
   */
  public Long DecryptByDisplay() {
    Long _sqrt = linearEquationOneUnknownDecrypt(this.a, this.b, this.encryptionId);
    return _sqrt * _sqrt - this.cha;
  }

  // 随机生成参数a,b
  public int[] randomAB() {
    int[] res = new int[2];
    Random r = new Random();
    while (true) {
      res[0] = r.nextInt(18000) - 9000;
      if (res[0] != 0) break;
    }
    res[1] = r.nextInt(2000) - 1000;
    return res;
  }

  // 加密 綫性方程 ax+b
  public Long linearEquationOneUnknown(int a, int b, Long sqrt) {
    return a * sqrt + b;
  }

  // 解密 綫性方程
  public Long linearEquationOneUnknownDecrypt(int a, int b, Long needDecryptNumber) {
    return (needDecryptNumber - b) / a;
  }

  public static void main(String[] args) throws Exception {

    SuperDisplay sd = new SuperDisplay(6200l);

    System.out.println("res:" + sd.setABAndGetId());
    System.out.println("jiemi:" + sd.DecryptByDisplay());
  }
  /**
   * 密 随机生成a，b生成新的加id
   *
   * @return
   * @throws Exception
   */
  public Long setABAndGetId() throws Exception {
    int[] ab = this.randomAB();
    this.a = ab[0];
    this.b = ab[1];
    return encryption(a, b, this.id);
  }

  // public Long getId() {
  // return id;
  // }

  public Long getEncryptionId() {
    return encryptionId;
  }

  public void setEncryptionId(Long encryptionId) {
    this.encryptionId = encryptionId;
  }
}
